#include <winhack.h>
//#include <elasys_server.h>
#include <elapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysconfig.h>

#include "camplus.h"

EXTERN FrameCapture g_frameCap;

CameraDriver g_CameraDriver;

BOOL CameraDriver::InitFrameDataInfo()
{
    BOOL ret;
    unsigned long SrcWidth;
    unsigned long SrcHeight;
    unsigned int  SrcPixelBs;

    g_frameCap.GetFrameDataInfo(&SrcWidth,
                                &SrcHeight,
                                &SrcPixelBs);

    ret = m_Converter.SetSrcFormat(SrcWidth,
                                     SrcHeight,
                                     SrcPixelBs);
    if(!ret){
        printf("Error: camera driver InitFrameDataInfo failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return FALSE;
    }

    ret = m_Shower.SetSrcFormat(SrcWidth,
                                  SrcHeight,
                                  SrcPixelBs);
    if(!ret){
        printf("Error: camera driver InitFrameDataInfo failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return FALSE;
    }

    return TRUE;
}


ECode  CameraDriver::CamDrv_Initialize()
{
    BOOL ret;

    m_pVideoRecorder = NULL;

    ret = m_Shower.Initialize();
    if(!ret){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return E_INVALID_OPERATION;
    }

    ret = m_Converter.Initialize();
    if(!ret){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        m_Shower.Destroy();
        return E_INVALID_OPERATION;
    }

    ret = (BOOL)g_frameCap.Initialize();
    if(!ret){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        m_Shower.Destroy();
        m_Converter.Destroy();
        return E_INVALID_OPERATION;
    }

    ret = InitFrameDataInfo();
    if(!ret){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        m_Shower.Destroy();
        m_Converter.Destroy();
        g_frameCap.Destroy();
        return E_INVALID_OPERATION;
    }

    //Default the photo mode
    m_PhotoSnapper = new PhotoSnapper;
    if(NULL == m_PhotoSnapper){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        m_Shower.Destroy();
        m_Converter.Destroy();
        g_frameCap.Destroy();
        return E_OUT_OF_MEMORY;
    }

    ret = m_PhotoSnapper->Initialize(&g_frameCap,
                                     &m_Shower,
                                     &m_Converter);
    if(!ret){
        printf("Error:camera driver CamDrv_Initialize failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        delete m_PhotoSnapper;
        m_PhotoSnapper = NULL;
        m_Shower.Destroy();
        m_Converter.Destroy();
        g_frameCap.Destroy();
        return E_INVALID_OPERATION;
    }

    return NOERROR;
}

void   CameraDriver::CamDrv_Quit()
{
    if(NULL != m_PhotoSnapper){
        m_PhotoSnapper->Destroy();
        delete m_PhotoSnapper;
        m_PhotoSnapper = NULL;
    }

    if(NULL != m_pVideoRecorder){
        m_pVideoRecorder->Destroy();
        delete m_pVideoRecorder;
        m_pVideoRecorder = NULL;
    }

    m_Shower.Destroy();

    m_Converter.Destroy();

    g_frameCap.Destroy();
}


ECode  CameraDriver::CamDrv_GetSnapFrames(Camera_Photo *pPhoto)
{
    if(NULL == m_PhotoSnapper){
        return E_INVALID_ARGUMENT;
    }
    return m_PhotoSnapper->SnapPhotos(pPhoto);
}

void PreviewCallBack(void *pFrameBuffer){
    g_CameraDriver.CamDrv_DoPreview(pFrameBuffer);
}


ECode  CameraDriver::CamDrv_BeginPreview(RECT *pRC)
{
    g_frameCap.StopCapture();
    g_CameraDriver.m_Shower.SetShowFormat(
        (pRC->right - pRC->left), (pRC->bottom - pRC->top));
    g_frameCap.BeginCapture(PreviewCallBack);

    return NOERROR;
}

void  CameraDriver::CamDrv_DoPreview(void *pFrameBuffer)
{
    g_CameraDriver.m_Shower.ShowFrame(pFrameBuffer);
}

ECode  CameraDriver::CamDrv_StopPreview()
{
    g_frameCap.StopCapture();

    return NOERROR;
}

void   CameraDriver::CamDrv_ReleaseFrames()
{
}

ECode  CameraDriver::CamDrv_SetAppFormat(unsigned int nID, int wParam, int lParam)
{
    ECode ec;

    if(NULL != m_PhotoSnapper){
        assert(NULL == m_pVideoRecorder);
        ec = m_PhotoSnapper->SetPhotoSnapperFormat(nID, wParam, lParam);
    } else {
        assert(NULL == m_PhotoSnapper);
        ec = m_pVideoRecorder->SetVideoRecorderFormat(nID, wParam, lParam);
    }

    return ec;
}

ECode  CameraDriver::CamDrv_GetAppFormat(unsigned int nID, int *pwParam, int *plParam)
{
    ECode ec;

    if(NULL != m_PhotoSnapper){
        assert(NULL == m_pVideoRecorder);
        ec = m_PhotoSnapper->GetPhotoSnapperFormat(nID, pwParam, plParam);
    } else {
        assert(NULL == m_PhotoSnapper);
        ec = m_pVideoRecorder->GetVideoRecorderFormat(nID, pwParam, plParam);
    }

    return ec;
}

ECode  CameraDriver::CamDrv_SetCamMode(int iMode)
{
    BOOL ret;

    if (0 == iMode) {//photo mode
        if(NULL != m_PhotoSnapper){
            return NOERROR;
        } else {
            m_PhotoSnapper = new PhotoSnapper;
            if(NULL == m_PhotoSnapper){
                printf("Error:camera driver CamDrv_SetCamMode failed! \
                file:%s. line:%d. \n",
                __FILE__, __LINE__);
                return E_OUT_OF_MEMORY;
            }

            ret = m_PhotoSnapper->Initialize(&g_frameCap,
                                             &m_Shower,
                                             &m_Converter);
            if(!ret){
                printf("Error:camera driver CamDrv_SetCamMode failed! \
                file:%s. line:%d. \n",
                __FILE__, __LINE__);
                delete m_PhotoSnapper;
                m_PhotoSnapper = NULL;
                return E_INVALID_OPERATION;
            }

            if(NULL != m_pVideoRecorder){
                m_pVideoRecorder->Destroy();
                delete(m_pVideoRecorder);
                m_pVideoRecorder = NULL;
            }
        }
    } else {          //video mode
        if(NULL != m_pVideoRecorder){
            return NOERROR;
        } else {
            m_pVideoRecorder = new VideoRecorder;
            if(NULL == m_pVideoRecorder){
                printf("Error:camera driver CamDrv_SetCamMode failed! \
                file:%s. line:%d. \n",
                __FILE__, __LINE__);
                return E_OUT_OF_MEMORY;
            }

            ret = m_pVideoRecorder->Initialize(&g_frameCap,
                                              &m_Shower,
                                              &m_Converter);
            if(!ret){
                printf("Error:camera driver CamDrv_SetCamMode failed! \
                file:%s. line:%d. \n",
                __FILE__, __LINE__);
                delete m_pVideoRecorder;
                m_pVideoRecorder = NULL;
                return E_INVALID_OPERATION;
            }

            if(NULL != m_PhotoSnapper){
                m_PhotoSnapper->Destroy();
                delete(m_PhotoSnapper);
                m_PhotoSnapper = NULL;
            }
        }
    }
    return NOERROR;
}

ECode  CameraDriver::CamDrv_BeginVideoRecord(IEvent ** ppOutEvent)
{
    if(NULL == m_pVideoRecorder){
        return E_INVALID_ARGUMENT;
    }
    return m_pVideoRecorder->BeginRecord(ppOutEvent);
}

ECode  CameraDriver::CamDrv_StopVideoRecord()
{
    if(NULL == m_pVideoRecorder){
        return E_INVALID_ARGUMENT;
    }
    return m_pVideoRecorder->StopRecord();
}

ECode  CameraDriver::CamDrv_GetVideoFrame(Camera_ImageFrame* pFrame)
{
    if(NULL == m_pVideoRecorder){
        return E_INVALID_ARGUMENT;
    }
    return m_pVideoRecorder->GetRecordFrame(pFrame);
}

//todo: may add lock
